#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import requests
import json
import time
from typing import Dict, List, Optional, Any, Tuple
from ones_config import ONES_CONFIG, API_ENDPOINTS

class OnesAPIClient:
    """ONES API客户端类 - 用于集成功能测试记录"""
    
    def __init__(self, base_url: str = None, user_id: str = None, auth_token: str = None, team_uuid: str = None):
        """
        初始化ONES API客户端
        
        Args:
            base_url: ONES服务器地址，默认使用配置文件中的地址
            user_id: 用户ID，默认使用配置文件中的ID
            auth_token: 认证token，默认使用配置文件中的token
            team_uuid: 团队UUID，默认使用配置文件中的UUID
        """
        self.base_url = base_url or ONES_CONFIG["base_url"]
        self.user_id = user_id or ONES_CONFIG["user_id"]
        self.auth_token = auth_token or ONES_CONFIG["auth_token"]
        self.team_uuid = team_uuid or ONES_CONFIG["team_uuid"]
        
        self.session = requests.Session()
        self.session.headers.update(self._get_headers())
        
    def _get_headers(self) -> Dict[str, str]:
        """获取API请求头"""
        return {
            "Content-Type": "application/json",
            "User-Agent": "OnesAPIClient/1.0",
            "Referer": f"{self.base_url}/",
            "Ones-User-Id": self.user_id,
            "Ones-Auth-Token": self.auth_token
        }
    
    def _build_url(self, endpoint_key: str, **kwargs) -> str:
        """构建API URL"""
        endpoint = API_ENDPOINTS[endpoint_key]
        endpoint = endpoint.format(
            team_uuid=self.team_uuid,
            **kwargs
        )
        return f"{self.base_url}{endpoint}"
    
    def _make_request(self, method: str, url: str, **kwargs) -> Tuple[bool, Any]:
        """
        发起API请求
        
        Returns:
            Tuple[bool, Any]: (是否成功, 响应数据或错误信息)
        """
        try:
            response = self.session.request(method, url, timeout=30, **kwargs)
            
            if response.status_code == 200:
                try:
                    return True, response.json()
                except:
                    return True, response.text
            else:
                return False, {
                    "status_code": response.status_code,
                    "error": response.text
                }
                
        except Exception as e:
            return False, {"error": str(e)}
    
    # ================== 用例库管理 ==================
    
    def get_libraries(self) -> Tuple[bool, Any]:
        """获取用例库列表"""
        url = self._build_url("libraries")
        return self._make_request("GET", url)
    
    def get_library_cases(self, library_uuid: str) -> Tuple[bool, Any]:
        """获取用例库中的测试用例"""
        # 首先尝试直接API
        url = self._build_url("library_cases", library_uuid=library_uuid)
        success, data = self._make_request("GET", url)
        
        if success and data.get("cases"):
            return success, data
            
        # 如果直接API没有返回用例，尝试GraphQL查询
        print(f"直接API返回空用例，尝试GraphQL查询...")
        return self._get_library_cases_graphql(library_uuid)
    
    def _get_library_cases_graphql(self, library_uuid: str) -> Tuple[bool, Any]:
        """使用GraphQL查询获取用例库中的测试用例"""
        url = self._build_url("library_cases_alt")
        
        # GraphQL查询语句
        graphql_query = {
            "query": """
            query {
              testcases(filter: {library_uuid: {equal: "%s"}}) {
                uuid
                name
                desc
                priority
                type
                assign
                module_uuid
                condition
                steps {
                  uuid
                  desc
                  result
                }
                create_time
                update_time
              }
            }
            """ % library_uuid
        }
        
        success, data = self._make_request("POST", url, json=graphql_query)
        
        if success and isinstance(data, dict):
            # 转换GraphQL响应格式
            testcases = data.get("data", {}).get("testcases", [])
            return True, {"cases": testcases}
        
        return success, data
    
    def get_library_cases_with_fallback(self, library_uuid: str) -> Tuple[bool, Any]:
        """获取用例库中的测试用例（带多种尝试方式）"""
        print(f"正在获取用例库 {library_uuid} 的用例...")
        
        # 方式1: 直接API
        url1 = self._build_url("library_cases", library_uuid=library_uuid)
        print(f"尝试方式1 - 直接API: {url1}")
        success1, data1 = self._make_request("GET", url1)
        
        if success1:
            cases = data1.get("cases", [])
            print(f"方式1结果: 获取到 {len(cases)} 个用例")
            if cases:
                return True, data1
        
        # 方式2: 尝试items接口
        url2 = f"{self.base_url}/project/api/project/team/{self.team_uuid}/items"
        print(f"尝试方式2 - Items接口: {url2}")
        
        # 查询参数
        params = {
            "library_uuid": library_uuid,
            "item_type": "testcase"
        }
        
        success2, data2 = self._make_request("GET", url2, params=params)
        if success2:
            items = data2.get("items", []) if isinstance(data2, dict) else []
            print(f"方式2结果: 获取到 {len(items)} 个items")
            if items:
                # 转换格式
                cases = []
                for item in items:
                    case = {
                        "uuid": item.get("uuid"),
                        "name": item.get("name"),
                        "desc": item.get("desc"),
                        "priority": item.get("priority"),
                        "type": item.get("type"),
                        "assign": item.get("assign"),
                        "module_uuid": item.get("module_uuid"),
                        "condition": item.get("condition"),
                        "steps": item.get("steps", []),
                        "create_time": item.get("create_time"),
                        "update_time": item.get("update_time")
                    }
                    cases.append(case)
                return True, {"cases": cases}
        
        # 方式3: GraphQL查询
        print("尝试方式3 - GraphQL查询")
        return self._get_library_cases_graphql(library_uuid)
    
    def create_library(self, name: str, members: Optional[List[str]] = None) -> Tuple[bool, Any]:
        """创建用例库"""
        url = self._build_url("add_library")
        
        payload = {"name": name}
        if members:
            payload["members"] = members
            
        return self._make_request("POST", url, json=payload)
    
    # ================== 测试计划管理 ==================
    
    def get_plans(self) -> Tuple[bool, Any]:
        """获取测试计划列表"""
        url = self._build_url("plans")
        return self._make_request("GET", url)
    
    def get_plan_cases(self, plan_uuid: str) -> Tuple[bool, Any]:
        """获取测试计划中的用例"""
        url = self._build_url("plan_cases", plan_uuid=plan_uuid)
        return self._make_request("GET", url)
    
    # ================== 测试用例管理 ==================
    
    def create_testcase(self, library_uuid: str, name: str, **kwargs) -> Tuple[bool, Any]:
        """
        创建测试用例
        
        Args:
            library_uuid: 用例库UUID
            name: 测试用例名称
            **kwargs: 其他可选参数
                - module_uuid: 模块UUID
                - priority: 优先级 (PRIOPThi, PRIOPTno, PRIOPTlo等)
                - type: 类型 (functional, performance, api等)
                - assign: 负责人UUID
                - desc: 描述
                - condition: 前置条件
                - steps: 操作步骤列表
        """
        url = self._build_url("add_testcase")
        
        payload = {
            "name": name,
            "library_uuid": library_uuid
        }
        payload.update(kwargs)
        
        return self._make_request("POST", url, json=payload)
    
    # ================== 便捷方法 ==================
    
    def find_library_by_name(self, name: str) -> Optional[Dict]:
        """根据名称查找用例库"""
        success, data = self.get_libraries()
        if not success:
            return None
            
        libraries = data.get("libraries", [])
        for library in libraries:
            if library.get("name") == name:
                return library
        return None
    
    def find_plan_by_name(self, name: str) -> Optional[Dict]:
        """根据名称查找测试计划"""
        success, data = self.get_plans()
        if not success:
            return None
            
        plans = data.get("plans", [])
        for plan in plans:
            if plan.get("name") == name:
                return plan
        return None
    
    def get_library_stats(self) -> Dict[str, Any]:
        """获取用例库统计信息"""
        success, data = self.get_libraries()
        if not success:
            return {"error": "Failed to get libraries"}
        
        libraries = data.get("libraries", [])
        stats = {
            "total_libraries": len(libraries),
            "libraries_detail": []
        }
        
        for library in libraries:
            library_info = {
                "uuid": library.get("uuid"),
                "name": library.get("name"),
                "create_time": library.get("create_time"),
                "modules_count": len(library.get("modules", []))
            }
            
            # 获取用例数量
            case_success, case_data = self.get_library_cases(library["uuid"])
            if case_success:
                library_info["cases_count"] = len(case_data.get("cases", []))
            else:
                library_info["cases_count"] = -1  # 获取失败
                
            stats["libraries_detail"].append(library_info)
            time.sleep(0.1)  # 避免请求过于频繁
        
        return stats
    
    def get_plan_stats(self) -> Dict[str, Any]:
        """获取测试计划统计信息"""
        success, data = self.get_plans()
        if not success:
            return {"error": "Failed to get plans"}
        
        plans = data.get("plans", [])
        stats = {
            "total_plans": len(plans),
            "plans_detail": []
        }
        
        for plan in plans:
            plan_info = {
                "uuid": plan.get("uuid"),
                "name": plan.get("name"),
                "owner": plan.get("owner"),
                "create_time": plan.get("create_time"),
                "todo_cases": plan.get("todo_case_count", 0),
                "passed_cases": plan.get("passed_case_count", 0),
                "failed_cases": plan.get("failed_case_count", 0),
                "blocked_cases": plan.get("blocked_case_count", 0),
                "skipped_cases": plan.get("skipped_case_count", 0)
            }
            
            plan_info["total_cases"] = (
                plan_info["todo_cases"] + 
                plan_info["passed_cases"] + 
                plan_info["failed_cases"] + 
                plan_info["blocked_cases"] + 
                plan_info["skipped_cases"]
            )
            
            if plan_info["total_cases"] > 0:
                plan_info["pass_rate"] = round(
                    plan_info["passed_cases"] / plan_info["total_cases"] * 100, 2
                )
            else:
                plan_info["pass_rate"] = 0
                
            stats["plans_detail"].append(plan_info)
        
        return stats


def main():
    """示例用法"""
    client = OnesAPIClient()
    
    print("🔍 ONES API客户端测试")
    print(f"Base URL: {client.base_url}")
    print(f"Team UUID: {client.team_uuid}")
    
    # 1. 获取用例库统计
    print(f"\n{'='*50}")
    print("📊 用例库统计信息")
    library_stats = client.get_library_stats()
    
    if "error" not in library_stats:
        print(f"总用例库数量: {library_stats['total_libraries']}")
        print(f"详细信息:")
        for lib in library_stats['libraries_detail']:
            print(f"  📁 {lib['name']}")
            print(f"     UUID: {lib['uuid']}")
            print(f"     用例数: {lib['cases_count']}")
            print(f"     模块数: {lib['modules_count']}")
    else:
        print(f"❌ 获取失败: {library_stats['error']}")
    
    # 2. 获取测试计划统计
    print(f"\n{'='*50}")
    print("📊 测试计划统计信息")
    plan_stats = client.get_plan_stats()
    
    if "error" not in plan_stats:
        print(f"总测试计划数量: {plan_stats['total_plans']}")
        print(f"详细信息:")
        for plan in plan_stats['plans_detail']:
            print(f"  📋 {plan['name']}")
            print(f"     UUID: {plan['uuid']}")
            print(f"     总用例: {plan['total_cases']}")
            print(f"     通过率: {plan['pass_rate']}%")
            print(f"     执行状态: 通过{plan['passed_cases']} 失败{plan['failed_cases']} 待执行{plan['todo_cases']}")
    else:
        print(f"❌ 获取失败: {plan_stats['error']}")
    
    # 3. 查找特定用例库
    print(f"\n{'='*50}")
    print("🔍 查找特定用例库")
    library_name = "小鹰卫士用例"
    found_library = client.find_library_by_name(library_name)
    
    if found_library:
        print(f"✅ 找到用例库: {found_library['name']}")
        print(f"   UUID: {found_library['uuid']}")
        print(f"   创建时间: {found_library['create_time']}")
        
        # 获取该库的测试用例
        success, cases_data = client.get_library_cases(found_library['uuid'])
        if success:
            cases = cases_data.get("cases", [])
            print(f"   用例数量: {len(cases)}")
            if cases:
                print("   前5个用例:")
                for i, case in enumerate(cases[:5], 1):
                    print(f"     {i}. {case.get('name', '未知名称')}")
        else:
            print(f"   ❌ 获取用例失败")
    else:
        print(f"❌ 未找到用例库: {library_name}")


if __name__ == "__main__":
    main() 